package com.mall.rabbitmq.demo2;

import com.rabbitmq.client.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author hyt
 * @date 2021/10/26
 */
@RestController
@RequestMapping("/send")
public class SendController {

    private final static String QUEUE_NAME = "hello";
    private static final String TASK_QUEUE_NAME = "task_queue";
    private static final String EXCHANGE_NAME = "logs";
    private static final String EXCHANGE_NAME2 = "direct_logs";

    public static void main(String[] argv) throws Exception {
        routePattern();
    }
    //注释版本
    public static void demo() throws Exception {
        //创建链接工厂对象
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置RabbitMQ服务主机地址,默认localhost
        connectionFactory.setHost("localhost");
        //设置RabbitMQ服务端口,默认5672
        connectionFactory.setPort(5672);
        //设置虚拟主机名字(在rabbitmq服务器中，消息队列是放在虚拟主机中的，这是为了更好分类管理各种消息队列，一般会加/)
        //虚拟主机名字得先在服务器中手动添加一个，否则会找不到虚拟主机
        connectionFactory.setVirtualHost("demo");
        //设置用户连接名，默认guest（你想用哪个rabbitmq服务器中的账户就填哪个的账号密码）
        connectionFactory.setUsername("guest");
        //设置链接密码，默认guest
        connectionFactory.setPassword("guest");
        //创建链接（在本身和rabbitmq服务器之间建立连接，类似跟redis、mysql之间建立连接）
        Connection connection = connectionFactory.newConnection();
        //创建频道(在本身和指定的rabbitmq服务器中的指定虚拟主机之间建立稳定、快速的通道)
        Channel channel = connection.createChannel();
        //声明队列（说明要在rabbitmq服务器中指定的虚拟主机中的哪条消息队列）
        /**
         * 声明队列
         * 参数1：队列名称
         * 参数2：是否定义持久化队列
         * 参数3：是否独占本次连接(其它连接是否能连接到本条队列)
         * 参数4：是否在不使用的时候自动删除队列
         * 参数5：队列其它参数
         * **/
        channel.queueDeclare(QUEUE_NAME,false,false,false,null);
        //创建消息
        String message = "hello!qianyi!";
        //消息发送
        /**
         * 消息发送
         * 参数1：交换机名称，如果没有指定则使用默认Default Exchage(不写就填空串)
         * 参数2：路由key,简单模式可以传递队列名称
         * 参数3：消息其它属性(没有填null)
         * 参数4：消息内容(消息内容是字符串，需要转换成字节数组才能传输)
         */
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        //关闭资源(连接和频道的)
        channel.close();
        connection.close();
    }


    //Worker模式
    public static void workerPattern() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        //创建频道(在本身和指定的rabbitmq服务器中的指定虚拟主机之间建立稳定、快速的通道)
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            /**
             * 声明队列
             * 参数1：队列名称
             * 参数2：是否定义持久化队列
             * 参数3：是否独占本次连接(其它连接是否能连接到本条队列)
             * 参数4：是否在不使用的时候自动删除队列
             * 参数5：队列其它参数
             * **/
            channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);

            String message = "tasequeue";
            //
            channel.basicQos(1);
            for(int i=0;i<20;i++){
                /**
                 * 消息发送
                 * 参数1：交换机名称，如果没有指定则使用默认Default Exchage(不写就填空串)
                 * 参数2：路由key,简单模式可以传递队列名称
                 * 参数3：消息其它属性(没有填null)
                 * 参数4：消息内容(消息内容是字符串，需要转换成字节数组才能传输)
                 */
                channel.basicPublish("", TASK_QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,(message+i).getBytes("UTF-8"));
            }

            System.out.println(" [x] Sent '" + message + "'");
        }
    }

    //Pub/Sub模式 先启动监听 后发送消息直接获取
    public static void pubPattern() throws Exception{
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            /**
             * 声明交换机
             * 参数1：交换机名称
             * 参数2：交换机类型，fanout、topic、direct、headers(以下用fanout类型，广播模式，每个与交换机绑定的队列都会接收到信息)
             * 参数3：交换机持久化 可去掉 默认是非持久化
             */
            channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.FANOUT,false);

            String message = "info: Hello World!";

            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }

    //路由模式 根据不同路由发送不同消息
    public static void routePattern() throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            //交换机
            channel.exchangeDeclare(EXCHANGE_NAME2, BuiltinExchangeType.DIRECT);
            //指定的可以
            String severity = "info";
            //消息内容
            String message = "directMsg";
            String errormessage = "errorMsg";

            channel.basicPublish(EXCHANGE_NAME2, severity, null, message.getBytes("UTF-8"));
            channel.basicPublish(EXCHANGE_NAME2, "error", null, errormessage.getBytes("UTF-8"));
            System.out.println(" [x] Sent '" + severity + "':'" + message + "'");
        }
    }
}
